package com.zusmart.core.condition.support;

import java.lang.annotation.Annotation;
import java.util.Map;

import com.zusmart.base.logging.Logger;
import com.zusmart.base.logging.LoggerFactory;
import com.zusmart.base.util.Assert;
import com.zusmart.core.bean.BeanDefinition;
import com.zusmart.core.condition.Condition;
import com.zusmart.core.condition.ConditionContext;
import com.zusmart.core.condition.ConditionFrom;
import com.zusmart.core.condition.ConditionType;
import com.zusmart.core.condition.Conditional;
import com.zusmart.core.config.ConfigSourceManager;
import com.zusmart.core.plugin.PluginManager;

public abstract class AbstractConditionContext implements ConditionContext {

	private static final Logger logger = LoggerFactory.getLogger(AbstractConditionContext.class);

	private final BeanDefinition sourceBeanDefinition;
	private final Conditional conditional;
	private final Annotation annotation;

	protected AbstractConditionContext(BeanDefinition sourceBeanDefinition, Conditional conditional, Annotation annotation) {
		Assert.isNull(sourceBeanDefinition, "source bean definition must not be null");
		Assert.isNull(conditional, "conditional must not be null");
		this.sourceBeanDefinition = sourceBeanDefinition;
		this.conditional = conditional;
		this.annotation = annotation;
	}

	@Override
	public BeanDefinition getSourceBeanDefinition() {
		return this.sourceBeanDefinition;
	}

	@Override
	public Conditional getNativeAnnotation() {
		return this.conditional;
	}

	@Override
	public Annotation getExtendAnnotation() {
		return this.annotation;
	}

	@Override
	public boolean isFromClass() {
		return this.getConditionFrom() == ConditionFrom.Class;
	}

	@Override
	public boolean isFromMethod() {
		return this.getConditionFrom() == ConditionFrom.Method;
	}

	@Override
	public boolean isTypeNative() {
		return this.getConditionType() == ConditionType.Native;
	}

	@Override
	public boolean isTypeExtend() {
		return this.getConditionType() == ConditionType.Extend;
	}

	@Override
	public boolean execute(Map<String, BeanDefinition> beanDefinitions, BeanDefinition targetBeanDefinition, PluginManager pluginManager, ConfigSourceManager configSourceManager) {
		Condition[] conditions = this.createConditionalInstance();
		if (null == conditions || conditions.length == 0) {
			return true;
		}
		for (Condition condition : conditions) {
			if (null != condition && condition.matches(this, beanDefinitions, targetBeanDefinition, pluginManager, configSourceManager) == false) {
				return false;
			}
		}
		return true;
	}

	protected Condition[] createConditionalInstance() {
		Class<? extends Condition>[] classes = this.conditional.value();
		if (null == classes || classes.length == 0) {
			return new Condition[0];
		}
		Condition[] result = new Condition[classes.length];
		for (int i = 0; i < classes.length; i++) {
			Class<? extends Condition> clazz = classes[i];
			try {
				result[i] = clazz.newInstance();
			} catch (Throwable e) {
				logger.warn("create condition instance error : " + e.getMessage());
			}
		}
		return result;
	}

}